﻿using System.Web.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace ValidationFramework.Web.MVC
{
	public class ClientValidationEngine
	{
	    readonly IClientValidationGenerator generator;
	    readonly IRuleExtractor extractor;
		readonly IRuleConverter converter;

		/// <summary>
		/// Initializes a new instance of the ClientValidationEngine class.
		/// </summary>
		/// <param name="extractor"></param>
		/// <param name="generator"></param>
		public ClientValidationEngine(IRuleExtractor extractor, IClientValidationGenerator generator, IRuleConverter converter)
		{
			this.generator = generator;
			this.extractor = extractor;
			this.converter = converter;
		}

		public string GenerateScript(string formId)
		{
			// extract rules
			var ruleList = this.extractor.Extract();

			var elementRules = TranslateToElementRules(ruleList);

			// generate script for elementRules
			var validationScript = generator.Generate(formId, elementRules);

			// wrap script in tag
			var scriptTag = new TagBuilder("script");
			scriptTag.Attributes.Add("type", "text/javascript");
			scriptTag.InnerHtml = validationScript;

			// return well formed scrip tag
			return scriptTag.ToString();
		}

		private ElementRuleDictionary TranslateToElementRules(IList<RuleInfo> ruleInfoList)
		{
			var rulesByProperty = from ruleInfo in ruleInfoList
								  group ruleInfo by ruleInfo.MemberName into g
								  select g;

			var elementRuleDictionary = new ElementRuleDictionary();

			foreach (var group in rulesByProperty)
			{
				// build client rules for element
				var clientRules = new List<IClientRule>();
				foreach (var item in group)
				{
					var clientRule = converter.ConvertToClientRule(item);
					if (clientRule != null)
						clientRules.Add(clientRule);
				}
				if (clientRules.Count > 0)
				{
					elementRuleDictionary.Add(group.Key, clientRules); // assume input element's id is the same as the property
				}
			}

			return elementRuleDictionary;
		}
	}
}
